require 'Object'

class ParticleEffect < DrawableObject
  attr_accessor :emission_rate, :max_particles, :particle_image
  
  attr_accessor :particle_lifespan
  attr_accessor :initial_scale, :end_scale
  attr_accessor :initial_alpha, :end_alpha
  attr_accessor :rotation_speed
  attr_accessor :randomization
  
  
  def initialize(image, rate, max, owner, lifespan=0)
    @particle_image = image
    @emission_rate  = rate # particles per second
    @max_particles  = max
    
    @time_to_next_particle = 1.0 / rate
    @num_particles = 0
    
    @lifespan = lifespan
    @lifetime = 0
    
    @owner = owner
    
    @particles = []
    
    # particle settings
    @particle_lifetime = 0.0
    @particle_lifespan = 1.0
    @initial_alpha = 1
    @end_alpha = 0
    @initial_scale = 1
    @end_scale = 0
    @rotation_speed = 15
    
    @randomization = 20
    
    super(nil)
  end
  
  def draw
    
  end
  
  def update
    if @lifespan != 0 then
      @lifetime += $dt
      destroy if @lifetime >= @lifespan
    end
    
    @time_to_next_particle -= $dt
    if @time_to_next_particle < 0 then
      new_particle
      @time_to_next_particle = 1.0 / @emission_rate
    end
    
    @particles.reject! {|particle| particle.lifetime >= particle.lifespan}
    
    super
  end
  
  def new_particle
    return nil if @num_particles >= @max_particles
    
    if @owner.is_a? CP::Vec2 then
      particle_pos = @owner
    elsif @owner.is_a? MovableObject then
      particle_pos = vect(@owner.body.p.x, @owner.body.p.y)
    end

    new_particle = Particle.new(@particle_image, particle_pos.x, particle_pos.y, @randomization)
    
    new_particle.lifespan = @particle_lifespan
    new_particle.initial_scale = @initial_scale
    new_particle.end_scale = @end_scale
    new_particle.initial_alpha = @initial_alpha
    new_particle.end_alpha = @end_alpha
    new_particle.rotation_speed = @rotation_speed    
    
    @particles << new_particle
    
  end
end

class Particle < DrawableObject
  attr_accessor :lifespan
  attr_reader :lifetime
  
  attr_accessor :initial_scale, :end_scale
  attr_accessor :initial_alpha, :end_alpha
  attr_accessor :rotation_speed
  attr_accessor :randomization
  
  
  def initialize(image, x, y, randomization)
    super(image)
    
    @lifetime = 0
    
    @x, @y = x,y
    
    @x += rand(randomization) - randomization / 2
    @y += rand(randomization) - randomization / 2
    
    @zindex = ZOrder::AirObjects
    
  end
  
  def update
    @lifetime += $dt
    destroy if @lifetime > @lifespan
    super
  end
  
  def draw
    draw_pos = $game.camera.adjusted_coords(@x, @y)
    
    alpha = Math::Easing::linear_tween(@lifetime, @initial_alpha, 
      (@end_alpha - @initial_alpha), @lifespan) * 255
    alpha = alpha.to_i
    if alpha < 0 then 
      alpha = 0 
    end
    scale = Math::Easing::linear_tween(@lifetime, @initial_scale, 
      (@end_scale - @initial_scale), @lifespan)
        
    colour = Gosu::Color.new(255,255,255,255)
    
		colour.alpha = alpha
    
		@image.draw_rot(draw_pos.x, draw_pos.y, ZOrder::Objects, @rotation_speed * @lifetime, 0.5,0.5, 
      scale, scale, colour)
  end
  
end

class Explosion < ParticleEffect
  def initialize(position)
    
    super(Images[:smoke1], 50, 20, position, 0.1)
    @randomization = 10
    @initial_scale = 0
    @end_scale = 1
		
		@blast_effect = ParticleEffect.new(Images[:explosion], 50, 20, position, 0.1)
		@blast_effect.initial_scale = 0.1
		@blast_effect.initial_alpha = 0.5
		@blast_effect.randomization = 0
		@blast_effect.end_scale = 2
		
  end
	
	def remove
		@blast_effect.remove
		super
	end
	
end

class Flash < DrawableObject
  def initialize(initial_colour, lifespan)
    if initial_colour.is_a? Gosu::Color then
      @colour = initial_colour
    else
      @colour = Gosu::Color.new(initial_colour)
    end
    @initial_alpha = @colour.alpha
    @lifespan = lifespan
    @lifetime = 0
    super(nil)
  end
  
  def update
    super
    @lifetime += $dt
    destroy if @lifetime >= @lifespan
  end
  
  def draw
    return if @lifetime >= @lifespan # avoid drawing <0 alpha
    alpha = Math::Easing::linear_tween(@lifetime, @initial_alpha, 
      (0 - @initial_alpha), @lifespan)
    @colour.alpha = alpha.to_i
    $game.draw_quad_with_coords(vect(0,0), vect(SCREEN_WIDTH, SCREEN_HEIGHT), 
      @colour, ZOrder::GUI)
  end
end
